/* Copyright 2012 Oliver Katz

    This file is part of Theta.

    Theta is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>. */

#ifndef __THETA_VM_BYTECODE_H
#define __THETA_VM_BYTECODE_H

#include <iostream>
#include <vector>

namespace vm
{
	using namespace std;

	const int _null = -0x01;
	const int _add = 0x00;
	const int _sub = 0x01;
	const int _mul = 0x02;
	const int _div = 0x03;
	const int _mod = 0x04;
	const int _and = 0x05;
	const int _or = 0x06;
	const int _xor = 0x07;
	const int _neg = 0x08;
	const int _lt = 0x09;
	const int _le = 0x0a;
	const int _gt = 0x0b;
	const int _ge = 0x0c;
	const int _eq = 0x0d;
	const int _neq = 0x0e;
	const int _fadd = 0x0f;
	const int _fsub = 0x10;
	const int _fmul = 0x11;
	const int _fdiv = 0x12;
	const int _flt = 0x13;
	const int _fle = 0x14;
	const int _fgt = 0x15;
	const int _fge = 0x16;
	const int _feq = 0x17;
	const int _fneq = 0x18;
	const int _br = 0x19;
	const int _push = 0x1a;
	const int _pop = 0x1b;
	const int _call = 0x1c;
	const int _al = 0x1d;
	const int _fr = 0x1e;
	const int _mov = 0x1f;
	const int _movi = 0x20;
	const int _fmov = 0x21;
	const int _fmovf = 0x22;
	const int _hldi = 0x23;
	const int _hsti = 0x24;
	const int _sld = 0x25;
	const int _sst = 0x26;

	const int _r0 = 0x00;
	const int _r1 = 0x01;
	const int _r2 = 0x02;
	const int _r3 = 0x03;
	const int _r4 = 0x04;
	const int _r5 = 0x05;

	const int _rret = 0x00;
	const int _ra0 = 0x01;
	const int _ra1 = 0x02;
	const int _rt0 = 0x03;
	const int _rt1 = 0x04;
	const int _rt2 = 0x05;

	string bytecodeToString(int op);
	string registerToString(int r);

	typedef struct 
	{
		int op;
		int a0;
		int a1;
		string f;
	} bytecode;

	class BytecodeClause
	{
	private:
		vector<bytecode> code;
		int lastReg;

	public:
		BytecodeClause();
		BytecodeClause(int lr);
		void write(int op, int a0, int a1);
		void write(int op, int a0) {write(op, a0, 0);}
		void write(int op, string f);
		vector<bytecode> read();
		void append(BytecodeClause c);
		void setLast(int lr);
		int last() {return lastReg;}
	};
}

#endif